package com.dick.base.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dick.base.dto.DictValueTreeNode;
import com.dick.base.exception.BaseRuntimeException;
import com.dick.base.exception.ExceptionProperties;
import com.dick.base.mapper.BaseDictMapper;
import com.dick.base.mapper.BaseDictValueMapper;
import com.dick.base.model.BaseDict;
import com.dick.base.model.BaseDictValue;
import com.dick.base.parameter.DictParameter;
import com.dick.base.parameter.DictValueParameter;
import com.dick.base.util.DateUtil;
import com.dick.base.util.IdUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * 字典service
 * @desc    字典服务，可以查询、修改、删除字典列表和字典值
 * @project 巡视与党风廉政建设系统
 * @company 北京远桥科技有限公司
 * @author  wanglei
 * @version 1.0
 * @date    2021-06-03
 */
@Service
public class DictService {

    @Autowired
    private BaseDictMapper baseDictMapper;
    @Autowired
    private BaseDictValueMapper baseDictValueMapper;

    /**
     * 获取字典列表（不包含逻辑删除的）
     * @return 字典列表
     */
    public List<BaseDict> baseDictList() {
        return baseDictMapper.selectList(null);
    }

    /**
     * 获取字典列表（包含逻辑删除的）
     * @return 字典列表
     */
    public List<BaseDict> baseDictAll() {
        return baseDictMapper.selectAll();
    }

    /**
     * 根据字典码获取字典值列表（不包含逻辑删除的）
     * @param code 字典码
     * @return 字典值列表
     */
    public List<BaseDictValue> baseDictValues(@NotNull String code) {
        BaseDictValue value = new BaseDictValue();
        value.setCode(code);
        return baseDictValueMapper.selectList(new QueryWrapper<>(value).orderByAsc("SORT_CODE"));
    }

    /**
     * 根据字典码获取字典值树（不包含逻辑删除的）
     * @param code 字典码
     * @return 字典值树
     */
    public List<DictValueTreeNode> baseDictValuesTree(@NotNull String code) {
        List<BaseDictValue> values = baseDictValues(code);
        return buildTreeNode(values);
    }

    private List<DictValueTreeNode> buildTreeNode(List<BaseDictValue> values) {
        Map<Long, DictValueTreeNode> idToNodeMap = new LinkedHashMap<>();
        values.stream().forEach(value -> {
            if (value.getParentId() == null) {
                idToNodeMap.put(value.getId(), new DictValueTreeNode(value));
            }
        });
        values.stream().forEach(value -> {
            if (value.getParentId() != null) {
                DictValueTreeNode node = idToNodeMap.get(value.getParentId());
                if (node == null) {
                    //父node缺失，自立门户
                    idToNodeMap.put(value.getId(), new DictValueTreeNode(value));
                } else {
                    //加进儿子里
                    node.getChildren().add(value);
                }
            }
        });
        return new ArrayList<>(idToNodeMap.values());
    }

    /**
     * 根据字典码获取字典值列表（包含逻辑删除的）
     * @param code 字典码
     * @return 字典值列表
     */
    public List<BaseDictValue> baseDictAllValues(@NotNull String code) {
        BaseDictValue value = new BaseDictValue();
        value.setCode(code);
        return baseDictValueMapper.selectValuesByCode(code);
    }

    /**
     * 根据字典码获取字典值树（包含逻辑删除的）
     * @param code 字典码
     * @return 字典值树
     */
    public List<DictValueTreeNode> baseDictAllValuesTree(@NotNull String code) {
        return buildTreeNode(baseDictAllValues(code));
    }

    /**
     * 新增或修改字典
     * @param dict
     * @return
     */
    @Transactional
    public BaseDict addOrModifyBaseDict(DictParameter dict) {
        BaseDict baseDict = new BaseDict();
        baseDict.setCode(dict.getCode());
        baseDict.setName(dict.getName());
        try {
            if (dict.getId() == null) {             //新增
                baseDict.setId(IdUtil.nextId());
                baseDict.setDeleted(false);
                baseDict.setCreateTime(DateUtil.now());
                baseDictMapper.insert(baseDict);
                return baseDict;
            } else {                                //修改
                BaseDict old = baseDictMapper.selectById(dict.getId());
                if (!old.getCode().equals(dict.getCode())) {
                    BaseDictValue dictValueUpdate = new BaseDictValue();
                    dictValueUpdate.setCode(dict.getCode());
                    BaseDictValue dictValueSelect = new BaseDictValue();
                    dictValueSelect.setCode(old.getCode());
                    baseDictValueMapper.update(dictValueUpdate, new QueryWrapper<>(dictValueSelect));
                }
                baseDict.setId(dict.getId());
                baseDict.setUpdateTime(DateUtil.now());
                baseDictMapper.updateById(baseDict);
                return baseDictMapper.selectById(dict.getId());
            }
        } catch (DataIntegrityViolationException e) {
            throw new BaseRuntimeException(ExceptionProperties.getInstance().getDictCodeDuplicated(),
                    HttpStatus.BAD_REQUEST, "code");
        }
    }

    /**
     * 删除字典（逻辑删除，不级联删除字典项）
     * @param id 字典主键
     */
    public void deleteBaseDict(Long id) {
        baseDictMapper.deleteById(id);
    }

    /**
     * 恢复字典（逻辑恢复）
     * @param id 字典主键
     */
    public void recoveryBaseDict(Long id) {
        baseDictMapper.recoveryById(id);
    }

    /**
     * 新增或修改字典值
     * @param value 字典值
     */
    @Transactional
    public void addOrModifyBaseDictValue(DictValueParameter value) {
        BaseDictValue dictValueCheck = new BaseDictValue();
        dictValueCheck.setCode(value.getCode());
        dictValueCheck.setCodeValue(value.getCodeValue());
        List<BaseDictValue> values  = baseDictValueMapper.selectList(new QueryWrapper<>(dictValueCheck));
        if (!values.isEmpty() && !values.get(0).getId().equals(value.getId())) {    //存在重复数据，不能继续执行
            throw new BaseRuntimeException(ExceptionProperties.getInstance().getDictCodeDuplicated(),
                    HttpStatus.BAD_REQUEST, "codeValue");
        }

        BaseDictValue dictValue = new BaseDictValue();
        dictValue.setCode(value.getCode());
        dictValue.setCodeLabel(value.getCodeLabel());
        dictValue.setCodeValue(value.getCodeValue());
        dictValue.setSortCode(value.getSortCode());
        dictValue.setParentId(value.getParentId());
        if (value.getId() == null) {                //插入
            dictValue.setDeleted(false);
            dictValue.setCreateTime(DateUtil.now());
            dictValue.setId(IdUtil.nextId());
            baseDictValueMapper.insert(dictValue);
        } else {                                    //修改
            dictValue.setCode(null);
            dictValue.setId(value.getId());
            dictValue.setUpdateTime(DateUtil.now());
            baseDictValueMapper.updateById(dictValue);
        }
    }

    /**
     * 删除字典值，逻辑删除，会级联逻辑删除儿子
     * @param id 主键
     */
    @Transactional
    public void deleteBaseDictValue(Long id) {
        BaseDictValue dictValueDelete = new BaseDictValue();
        dictValueDelete.setParentId(id);
        baseDictValueMapper.deleteById(id);
        baseDictValueMapper.delete(new QueryWrapper<>(dictValueDelete));
    }

}
